package net.animats.music;

import java.util.List;
import java.util.ArrayList;

public class IntervalSet {

    private String name;
    private String shortName;
    private List<Integer> intervals = new ArrayList<Integer>();

    // THESE ARE THE INTERVALS STARTING AT THE ROOT OF THE MAJOR SCALE. ALL OTHER
    // SCALES ARE SPECIFIED RELATIVE TO THIS SCALE.

    public static final int[] majorScaleIntervals = {0, 2, 4, 5, 7, 9, 11};
    // AN ARRAY OF NOTE NAMES, STARTING AT 'A' FOR THIS TYPE OF SCALE.
    // THE nameIndex OF A NOTE CAN BE USED AS THE INDEX OF THIS ARRAY TO FIND
    // THE CORRECT NAME OF THE NOTE WHEN IN THE CONTECT OF THIS SCALE.

    public static final int NATURAL = 0;
    public static final int FLAT = -1;
    public static final int SHARP = +1;

    public IntervalSet(String _name, String _shortName) {
        name = _name;
        shortName = _shortName;
    }

    public IntervalSet(String _name, String _shortName, Integer... _intervals) {
        name = _name;
        shortName = _shortName;

        for (Integer currentInterval : _intervals) {
            intervals.add(currentInterval);
        }
    }

    public void setName(String _name) {
        name = _name;
    }

    public String getName() {
        return name;
    }

    public void setShortName(String _shortName) {
        shortName = _shortName;
    }

    public String getShortName() {
        return shortName;
    }

    public List<Integer> getIntervals() {
        return intervals;
    }

    public String toString() {
        String temp = "";

        for (Integer interval : intervals) {
            temp += interval + " ";
        }

        return temp;
    }

    public void syncIntervals(NoteSet _noteSet) {
        int baseIndex;
        int tempInterval;

        // IS THE NoteSet EMPTY?
        if (_noteSet.getSize() == 0) {
            return;
        }

        // IS THE ROOT NOTE KNOWN?
        if (_noteSet.getRootNote() == null) {
            // NO, PRESUME FIRST NOTE IS ROOT NOTE
            baseIndex = _noteSet.getNotes().get(0).getIndex();
        } else {
            baseIndex = _noteSet.getRootNote().getIndex();
        }

        intervals.clear();

        for (Note currentNote : _noteSet.getNotes()) {
            tempInterval = currentNote.getIndex() - baseIndex;
            if (tempInterval < 0) {
                // ADD AN OCTAVE TO GET THE NEXT HIGHEST NOTE OF THE CORRECT TYPE
                tempInterval += 12;
            }
            intervals.add(tempInterval);
        }

        // NOW TEST IF THIS IntervalSet IS A KNOWN ScaleType OR A KNOW ChordType
        IntervalSet determinedIntervalSet = determinedIntervalSet = ChordType.getChordType(this);

        if (determinedIntervalSet == null) {
            determinedIntervalSet = ScaleType.getScaleType(this);
        }

        if (determinedIntervalSet != null) {
            setName(determinedIntervalSet.getName());
            setShortName(determinedIntervalSet.getShortName());
        } else {
            setName("Unknown");
            setShortName("Unk");
        }
    }

    public boolean equals(Object _intervalSet) {
        //System.out.println("Comparing " + ((IntervalSet)_intervalSet).toString() + " and " + toString());
        if (_intervalSet instanceof IntervalSet) {
            for (Integer currentInterval : intervals) {
                if (((IntervalSet) _intervalSet).getIntervals().contains(currentInterval) == false) {
                    // THERE IS A INTERVAL IN THIS IntervalSet THAT ISN'T
                    // IN THE PASSED IntervalSet
                    return false;
                }
            }

            for (Integer currentInterval : ((IntervalSet) _intervalSet).getIntervals()) {
                if (intervals.contains(currentInterval) == false) {
                    // THERE IS A INTERVAL IN THE PASSED IntervalSet THAT ISN'T
                    // IN THIS IntervalSet

                    return false;
                }
            }

            return true;

        } else {
            return false;
        }
    }

    public void addInterval(Integer _interval) {
        intervals.add(_interval);
    }

    public String getLabel() {
        return name;
    }
}
